#include "BearAgent.h"
#include "AgentManager.h"
BearAgent::BearAgent()
{
}

BearAgent::~BearAgent()
{
}

void BearAgent::Initialize(std::vector<std::vector<Node*>> &pGrid)
{
	m_xBuffer.loadFromFile("Sound/Bite_High.ogg");
	m_xSound.setBuffer(m_xBuffer);
	Agent::Initialize(pGrid);
	m_iSenseRange = 4;
	m_xSprite = m_xSpriteManager->LoadSprite("Images/Bear.png", 5);
	m_xSprite->setOrigin(12.5f, 12.5f);
	m_fMoveSpeed = 5.5f;
	m_xAnimalType = Bear;
	m_fHunger = 60;

	//Setting up the behavior tree. 
	//I create a sequncer and two action bide children. 
	//If the first child succeds, it goes to the second which then gets executed. Otherwise it fails and does nothing.
	SequencerBNode* wanderSeq = new SequencerBNode();
	BearAgentActionBnode* wander = new BearAgentActionBnode();
	BearAgentActionBnode* timeCheck = new BearAgentActionBnode();
	SelectorBNode* rootSel = new SelectorBNode();

	SequencerBNode* foodSeq = new SequencerBNode();
	BearAgentActionBnode *lookFood = new BearAgentActionBnode();
	BearAgentActionBnode *goFood = new BearAgentActionBnode();
	BearAgentActionBnode *eatFood = new BearAgentActionBnode();

	lookFood->SetAgent(this);
	lookFood->FunctionPointer = &BearAgent::CheckForFood;
	goFood->SetAgent(this);
	goFood->FunctionPointer = &BearAgent::WalkTowardsFood;
	eatFood->SetAgent(this);
	eatFood->FunctionPointer = &BearAgent::EatFood;
	foodSeq->AddChildNode(lookFood);
	foodSeq->AddChildNode(goFood);
	foodSeq->AddChildNode(eatFood);



	timeCheck->SetAgent(this);
	wander->SetAgent(this);
	timeCheck->FunctionPointer = &BearAgent::TimeCheck;
	wander->FunctionPointer = &BearAgent::Wander;
	wanderSeq->AddChildNode(timeCheck);
	wanderSeq->AddChildNode(wander);

	rootSel->AddChildNode(foodSeq);
	rootSel->AddChildNode(wanderSeq);



	m_xNode = rootSel;
}

void BearAgent::Update(float pDeltaTime)
{
	/*if (m_fIdleTimer <= 0.0f && m_bFinishedPath)
	{*/
	SearchArea();
	//	m_fIdleTimer = 2.0f;
	//}
	if (m_fIdleTimer > 0.0f && m_bFinishedPath)
	{
		m_fIdleTimer -= pDeltaTime;
	}

	Agent::Update(pDeltaTime);
}

void BearAgent::Cleanup()
{
	Agent::Cleanup();
}

void BearAgent::SearchArea()
{
	// Find somewhere to go.
	// Look at all the nodes in the sense range and add anything interesting to a list
	Think();
}

void BearAgent::Think()
{
	// Evaluate options
	// Look through the list of interesting things and find the best one for the agent to do
	SearchArea2();
	m_xNode->Run();
	//Act();
}

void BearAgent::Act()
{
	// Interact with objects
	// If the target is not within range to interact with travel to the node and then interact

	// Find path to random node
	//if (m_bFinishedPath)
	//{
	//	sf::Vector2i curNodeID = m_xCurrentNode->m_vID;

	//	// Find a random node within the sense range and find a path too that node.
	//	bool foundTarget = false;
	//	while (!foundTarget)
	//	{
	//		int RandX = rand() % ((m_iSenseRange * 2) + 1) + (-m_iSenseRange);
	//		int RandY = rand() % ((m_iSenseRange * 2) + 1) + (-m_iSenseRange);

	//		if ((curNodeID.x + RandX <= 29) && (curNodeID.x + RandX >= 0) && (curNodeID.y + RandY <= 29) && (curNodeID.y + RandY >= 0))
	//		{
	//			if ((Grid[curNodeID.x + RandX][curNodeID.y + RandY]->m_bBlocked == false))
	//			{
	//				// Use A* to find a path to the node
	//				if (FindPath(Grid[curNodeID.x + RandX][curNodeID.y + RandY]))
	//				{
	//					// Travel to this node
	//					Travel();
	//					foundTarget = true;
	//				}
	//			}
	//		}
	//	}
	//}
}



int BearAgent::Wander(BNode::Status p_Status)
{
	// Find path to random node
	if (m_bFinishedPath)
	{
		sf::Vector2i curNodeID = m_xCurrentNode->m_vID;

		// Find a random node within the sense range and find a path too that node.
		bool foundTarget = false;
		while (!foundTarget)
		{
			int RandX = rand() % ((m_iSenseRange * 2) + 1) + (-m_iSenseRange);
			int RandY = rand() % ((m_iSenseRange * 2) + 1) + (-m_iSenseRange);

			if ((curNodeID.x + RandX <= 29) && (curNodeID.x + RandX >= 0) && (curNodeID.y + RandY <= 29) && (curNodeID.y + RandY >= 0))
			{
				if ((Grid[curNodeID.x + RandX][curNodeID.y + RandY]->m_bBlocked == false) && (Grid[curNodeID.x + RandX][curNodeID.y + RandY] != m_xCurrentNode))
				{
					FindPath(Grid[curNodeID.x + RandX][curNodeID.y + RandY]);
					Travel();
					foundTarget = true;
					return BNode::Running;

				}
			}
		}

	}

}

int BearAgent::TimeCheck(BNode::Status p_Status)
{
	if (m_fIdleTimer <= 0.0f && m_bFinishedPath)
	{

		m_fIdleTimer = 2.0f;
		return BNode::Succeded;
	}
	return BNode::Failed;
}



int BearAgent::CheckForFood(BNode::Status p_Status)
{

	for (int i = 0; i < m_CData.m_SearchDataList.size(); i++)
	{
		if (m_CData.m_SearchDataList[i]->m_Node->m_vAgents.size() != 0)
		{
			for (int y = 0; y < m_CData.m_SearchDataList[i]->m_Node->m_vAgents.size(); y++)
			{
				if (m_CData.m_SearchDataList[i]->m_Node->m_vAgents[y]->GetAnimalType() == Animals::Wolf)
				{
					m_CData.ClosestFood = m_CData.m_SearchDataList[i]->m_Node;
					return BNode::Succeded;
				}
			}
		}
	}
	return BNode::Failed;
}
int BearAgent::WalkTowardsFood(BNode::Status p_Status)
{
	if (p_Status != BNode::Running)
	{

		vector<NodeSenseData*> tempData;
		//find all nodes with target in them and put in a vector.
		int currentMD = 0;
		for (int i = 0; i < m_CData.m_SearchDataList.size() - 1; i++)
		{
			if (m_CData.m_SearchDataList[i]->m_Node->m_vAgents.size() != 0)
			{
				for (int y = 0; y < m_CData.m_SearchDataList[i]->m_Node->m_vAgents.size(); y++)
				{

					if (m_CData.m_SearchDataList[i]->m_Node->m_vAgents[y]->GetAnimalType() == Animals::Wolf)
					{

						m_CData.m_SearchDataList[i]->m_ManhattanDistance = aStar.CalculateMDistance(m_xCurrentNode, m_CData.m_SearchDataList[i]->m_Node);
						tempData.push_back(m_CData.m_SearchDataList[i]);
						//But since your collecting nodes,
						//if there are multiple targets on the same node it doesnt matter.

						break;
					}
				}
			}
		}



		//Sort said vector. (bubble sort)
		NodeSenseData* myTemporaryNode;
		int end = 0;

		while (end++ != tempData.size()) //
		{
			bool swapped = false;
			for (int i = 0; i < tempData.size() - 1; i++)
			{

				if (tempData[i]->m_ManhattanDistance > tempData[i + 1]->m_ManhattanDistance)
				{
					myTemporaryNode = tempData[i];

					tempData[i] = tempData[i + 1];
					tempData[i + 1] = myTemporaryNode;
					swapped = true;
				}
			}
			//fast exit
			if (!swapped) break;
		}

		//now, depending on the amount of targets
		//Either just pick the first one:
		if (tempData.size() > 0)
		{
			int randomVector = 0;
			if (tempData.size() > 3)
			{
				//or pick a random one of the first few elements (lowest MD)
				//Now this is kinda hard to scale properly, but i tried.
				randomVector = rand() & (tempData.size() / 3);
				//randomVector =( tempData.size() - randomVector) - 1;
				std::cout << "BearTargets: " << tempData.size() << " Bear picked target number: " << randomVector << "\n";
			}

			if (tempData[randomVector]->m_Node != m_xCurrentNode)
			{
				FindPath(tempData[randomVector]->m_Node);
				m_CData.ClosestFood = tempData[randomVector]->m_Node;
				Travel();
				return BNode::Running;
			}
			else
			{
				return BNode::Failed;
			}
		}
		else
		{
			return BNode::Failed;
		}
	}

	if (!m_bFinishedPath)
	{
		return BNode::Running;
	}
	else
	{

		return BNode::Succeded;
	}

}
int BearAgent::EatFood(BNode::Status p_Status)
{

	if (m_CData.ClosestFood == m_xCurrentNode)
	{
		for (int j = 0; j < m_CData.ClosestFood->m_vAgents.size(); j++)
		{
			if (m_CData.ClosestFood->m_vAgents[j]->GetAnimalType() == Animals::Wolf)
			{
				if (m_CData.ClosestFood->m_vAgents[j]->ShouldKill() == false)
				{
				//m_CData.ClosestFood->m_xWorldObject->StartDeletion();
				m_fHunger += 100;
				std::cout << "Bear Eat! " << "\n";
				m_CData.ClosestFood->m_vAgents[j]->ShouldBeDeleted();
				if (m_fHunger > 200)
					{
						AgentManager::GetInstance()->SpawnAnimal(Animals::Bear, m_xCurrentNode);
						m_fHunger -= 30;
					}
				m_xSound.play();
				return BNode::Succeded;
				}
			}
		}

	}
	//std::cout << "No food here Q_Q" << "\n";

	return BNode::Failed;
}